`timescale 1ns / 1ps

module CurryALU_tb;

    // Testbench signals
    reg clk, rst_n;
    reg [15:0] i_data;
    reg [1:0] i_op;
    reg i_iter_tag;
    reg i_wr_force;
    reg i_wr_result;
    reg i_rd_acc; // Not used in the current implementation
    wire [15:0] o_data;

    // Instantiate the DUT (Device Under Test)
    CurryALU uut (
        .clk(clk),
        .rst_n(rst_n),
        .i_data(i_data),
        .i_op(i_op),
        .i_iter_tag(i_iter_tag),
        .i_wr_force(i_wr_force),
        .i_wr_result(i_wr_result),
        .i_rd_acc(i_rd_acc),
        .o_data(o_data)
    );

    // Clock generation
    initial clk = 0;
    always #5 clk = ~clk; // 100 MHz clock

    // Test cases
    initial begin
        // Initialize signals
        rst_n = 0;
        i_data = 0;
        i_op = 0;
        i_iter_tag = 0;
        i_wr_force = 0;
        i_wr_result = 0;
        i_rd_acc = 0;

        // Reset the system
        #10 rst_n = 1;

        // Test Case 1: Addition
        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b00; // Addition
        i_wr_force = 1; // Force write to acc_data_reg
        #10 i_wr_force = 0;

        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b00; // Addition
        i_iter_tag = 0; // Not an iteration
        #10 i_iter_tag = 0;

        #10 $display("Test Case 1: Add 1.0 + 1.0 = %b", o_data);

        // Test Case 2: Subtraction
        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b01; // Subtraction
        i_wr_force = 1; // Force write to acc_data_reg
        #10 i_wr_force = 0;

        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b01; // Subtraction
        i_iter_tag = 0; // Not an iteration
        #10 i_iter_tag = 0;

        #10 $display("Test Case 2: Sub 1.0 - 1.0 = %b", o_data);

        // Test Case 3: Multiplication
        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b10; // Multiplication
        i_wr_force = 1; // Force write to acc_data_reg
        #10 i_wr_force = 0;

        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b10; // Multiplication
        i_iter_tag = 0; // Not an iteration
        #10 i_iter_tag = 0;

        #10 $display("Test Case 3: Mul 1.0 * 1.0 = %b", o_data);

        // Test Case 4: Division
        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b11; // Division
        i_wr_force = 1; // Force write to acc_data_reg
        #10 i_wr_force = 0;

        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b11; // Division
        i_iter_tag = 0; // Not an iteration
        #10 i_iter_tag = 0;

        #10 $display("Test Case 4: Div 1.0 / 1.0 = %b", o_data);

        // Test Case 5: Iteration
        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b00; // Addition
        i_iter_tag = 1; // Iteration
        i_wr_force = 1; // Force write to acc_data_reg
        #10 i_wr_force = 0;

        i_data = 16'b0_01111_0000000000; // 1.0 (BF16)
        i_op = 2'b00; // Addition
        i_iter_tag = 1; // Iteration
        #10 i_iter_tag = 0;

        #10 $display("Test Case 5: Iterative Add 1.0 + 1.0 = %b", o_data);

        // Finish simulation
        #10 $finish;
    end

endmodule